package com;

import com.conn.ConnectionUtil;
import com.entity.FiledModelOfEntity;
import com.entity.MethodModelOfEntity;
import com.entity.ProductCodeModelOfEntity;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;

import java.io.*;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

public class ProductCodeModel {
    private String[] nums = {"java.lang.Integer", "java.lang.Long", "java.lang.Double", "java.lang.Float"};
    private String[] intType = {"smallint", "int", "TINYINT", "tinyint", "INTEGER"};
    private String[] dateType = {"datetime", "TIMESTAMP"};
    private String[] booleanType = {"bit"};
    private String[] LongType = {"BIGINT"};
    private String[] bigdecType = {"numeric", "decimal"};
    private String[] LocalDateType = {"date"};

    public boolean choose(ProductCodeModelOfEntity entity) throws Exception {
        entity = initEntity(entity);
        String primaryKeyStr = getPrimaryKeyColumns(entity);
        List<Map<String, String>> dataList = getColumnsData(entity);

        if (Objects.isNull(dataList) || dataList.size() == 0) {
            throw new RuntimeException("【" + entity.getTable() + "】表名错误;查不到对应的列");
        }
        String comment = getTableComment(entity);
        entity.setTableComment(comment);


        combData(entity, dataList, primaryKeyStr);
        chooseEntityTemplate(entity, dataList, primaryKeyStr);
        chooseAddDTO(entity);
        chooseUpdateDTO(entity);
        if (Objects.equals("1", entity.getStatucFlag())) {
            chooseUpdateStatusDTO(entity);
        }
        chooseQueryDTO(entity);
        chooseVO(entity);
        chooseMapper(entity);
        chooseMapperXML(entity);
        chooseService(entity);
        chooseServiceImpl(entity);
        chooseController(entity);
        choosePage(entity);

        return Boolean.TRUE;
    }

    /***
     * 生成页面信息
     * @author liujun
     * @date 2024/6/19 13:28
     * @param entity
     * @return boolean
     */
    private boolean choosePage(ProductCodeModelOfEntity entity) throws Exception {
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("entity", entity);

        dataMap.put("url", entity.getUrl());
        dataMap.put("filedList", createFiled(entity, false));
        dataMap.put("statucFlag", entity.getStatucFlag());
        dataMap.put("idFiled", entity.getIdFiled());

        List<String> selectFile = new ArrayList<>();
        List<String> fileds = new ArrayList<>();

        entity.getFiledModelOfEntities().stream().filter(en -> Objects.equals(en.getHaveId(), 1)).collect(Collectors.toList()).stream().forEach(en -> {
            selectFile.add(formatName(en.getName()));
            fileds.add(formatResourceName(en.getName()));
        });
        dataMap.put("selectFile", selectFile);
        dataMap.put("fileds", fileds);


        boolean templFlag = true;
        boolean jsFlag = true;
        if (org.apache.commons.lang3.StringUtils.isNotEmpty(entity.getPagePath())) {
            String jsPath = org.apache.commons.lang3.StringUtils.replace(entity.getJsPath(),"\\","/");
            jsPath= org.apache.commons.lang3.StringUtils.substringAfter(entity.getJsPath(),"api");

            dataMap.put("jsPath",jsPath);
            templFlag = writeClassOfModel("temp.ftl", (entity.getPagePath()), entity.getResourceName(), entity, dataMap, "vue");
        }

        if (org.apache.commons.lang3.StringUtils.isNotEmpty(entity.getJsPath())) {
            jsFlag = writeClassOfModel("js.ftl", (entity.getJsPath()), entity.getResourceName(), entity, dataMap, "js");
        }


        return templFlag & jsFlag;
    }

    /***
     *
     * 生成 controller代码
     * @param entity
     * @return
     * @throws Exception
     */
    private boolean chooseController(ProductCodeModelOfEntity entity) throws Exception {
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("entity", entity);
        dataMap.put("entityName", entity.getEntityName());
        dataMap.put("packageStr", entity.getControllerPackageStr());
        dataMap.put("servicePath", entity.getServicePath());
        dataMap.put("voPath", entity.getVoPath());
        dataMap.put("voName", entity.getVoName());
        dataMap.put("addDtoPath", entity.getAddDtoPath());
        dataMap.put("addDTO", entity.getAddDtoName());
        dataMap.put("updateDtoPath", entity.getUpdateDtoPath());
        dataMap.put("updateStatusDTOPath", entity.getUpdateStatusDTOPath());
        dataMap.put("updateDTO", entity.getUpdateDtoName());
        dataMap.put("queryDTO", entity.getQueryDtoName());
        dataMap.put("queryDtoPath", entity.getQueryDtoPath());
        dataMap.put("url", entity.getUrl());
        dataMap.put("controllerName", entity.getControllerName());
        dataMap.put("serviceName", entity.getServiceName());
        dataMap.put("serviceNm", entity.getServiceNm());
        dataMap.put("idFiled", entity.getIdFiled());
        dataMap.put("idFiledType", entity.getIdType());
        dataMap.put("resultClass", entity.getResultClass());
        dataMap.put("statucFlag", entity.getStatucFlag());
        dataMap.put("updateStatusDTO", entity.getUpdateStatusDTOName());
        dataMap.put("successMethod", entity.getSuccessMethod());
        dataMap.put("errorMethod", entity.getErrorMethod());
        dataMap.put("idType", entity.getIdType());
        dataMap.put("entityPath", entity.getEntityPath());


        return writeClassOfModel("controller.ftl", (entity.getControllerStr()), entity.getControllerName(), entity, dataMap, "java");
    }

    /***
     * 生成service impl  方法
     * @param entity
     * @return
     * @throws Exception
     */
    private boolean chooseServiceImpl(ProductCodeModelOfEntity entity) throws Exception {
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("entity", entity);
        dataMap.put("packageStr", entity.getServiceImplPackageStr());
        dataMap.put("entityPath", entity.getEntityPath());
        dataMap.put("mapperPath", entity.getMapperPath());
        dataMap.put("servicePath", entity.getServicePath());
        dataMap.put("serviceImplName", entity.getServiceImplName());
        dataMap.put("mapperName", entity.getMapperName());
        dataMap.put("serviceName", entity.getServiceName());
        dataMap.put("entityName", entity.getEntityName());
        dataMap.put("repostioryName", entity.getRepostioryName());
        dataMap.put("statucFlag", entity.getStatucFlag());
        dataMap.put("idType", entity.getIdType());
        dataMap.put("idFiled", entity.getIdFiled());
        dataMap.put("orderMethodList", entity.getMethodModelOfEntities());
        dataMap.put("orderDataList", entity.getColumns());
        dataMap.put("filedList", createFiled(entity, true));

        String idMethod = "";
        List<MethodModelOfEntity> methodModelOfEntities = entity.getMethodModelOfEntities();
        if (!CollectionUtils.isEmpty(methodModelOfEntities)) {
            Optional<MethodModelOfEntity> optional = methodModelOfEntities.stream().filter(m -> Objects.equals(m.getFiled(), entity.getIdFiled())).findFirst();
            if (optional.isPresent()) {
                idMethod = optional.get().getGetName();
            }
        }
        dataMap.put("idMethod", idMethod);
        dataMap.put("idColumn", entity.getIdColumn());

        return writeClassOfModel("serviceImpl.ftl", (entity.getServiceImplStr()), entity.getServiceImplName(), entity, dataMap, "java");
    }

    /***
     * 生成 service方法
     * @param entity
     * @return
     * @throws Exception
     */
    private boolean chooseService(ProductCodeModelOfEntity entity) throws Exception {
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("packageStr", entity.getServicePackageStr());
        dataMap.put("entityPath", entity.getEntityPath());
        dataMap.put("serviceName", entity.getServiceName());
        dataMap.put("entityName", entity.getEntityName());
        dataMap.put("statucFlag", entity.getStatucFlag());


        dataMap.put("idType", entity.getIdType());
        dataMap.put("idFiled", entity.getIdFiled());
        dataMap.put("entity", entity);

        return writeClassOfModel("service.ftl", (entity.getServiceStr()), entity.getServiceName(), entity, dataMap, "java");
    }

    /***
     * 生成mapper xml文件
     * @param entity
     * @return
     * @throws Exception
     */
    private boolean chooseMapperXML(ProductCodeModelOfEntity entity) throws Exception {
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("mapperPath", entity.getMapperPath());
        dataMap.put("entityPath", entity.getEntityPath());
        dataMap.put("filedList", entity.getFiledModelOfEntities());
        dataMap.put("table", entity.getTable());
        dataMap.put("idColumn", entity.getIdColumn());
        dataMap.put("idFiled", entity.getIdFiled());
        dataMap.put("entity", entity);

        return writeClassOfModel("mapperXML.ftl", entity.getMapperXMLStr(), entity.getMapperName(), entity, dataMap, "xml");
    }

    /***
     *  组合 mapper对象
     * @param entity
     * @return
     */
    private boolean chooseMapper(ProductCodeModelOfEntity entity) throws Exception {
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("packageStr", entity.getMapperPackageStr());
        dataMap.put("entityPath", entity.getEntityPath());
        dataMap.put("mapperName", entity.getMapperName());
        dataMap.put("entityName", entity.getEntityName());
        dataMap.put("entity", entity);

        return writeClassOfModel("mapper.ftl", (entity.getMapperStr()), entity.getMapperName(), entity, dataMap, "java");

    }

    /***
     * 生成 addDTO
     * @param entity
     * @return
     * @throws Exception
     */
    private boolean chooseAddDTO(ProductCodeModelOfEntity entity) throws Exception {
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("packageStr", entity.getAddDtoPackageStr());
        dataMap.put("dtoName", entity.getAddDtoName());
        dataMap.put("value", createSerialVersionUID());
        dataMap.put("jsonUtilMethod", entity.getVoDtoJsonUtilMethod());

        dataMap.put("filedList", createFiled(entity, true));
        dataMap.put("methodList", createMethod(entity, true));

        dataMap.put("entity", entity);
        dataMap.put("dtoValue", "添加");


        return writeClassOfModel("dto.ftl", (entity.getDtoStr()), entity.getAddDtoName(), entity, dataMap, "java");
    }

    /***
     * 生成 updateDTO
     * @param entity
     * @return
     * @throws Exception
     */
    private boolean chooseUpdateDTO(ProductCodeModelOfEntity entity) throws Exception {
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("packageStr", entity.getUpdateDtoPackageStr());
        dataMap.put("dtoName", entity.getUpdateDtoName());
        dataMap.put("value", createSerialVersionUID());
        dataMap.put("jsonUtilMethod", entity.getVoDtoJsonUtilMethod());
        dataMap.put("filedList", createFiled(entity, true));
        dataMap.put("methodList", createMethod(entity, true));

        dataMap.put("entity", entity);
        dataMap.put("dtoValue", "修改");


        return writeClassOfModel("dto.ftl", (entity.getDtoStr()), entity.getUpdateDtoName(), entity, dataMap, "java");
    }

    /***
     * 生成 updateDTO
     * @param entity
     * @return
     * @throws Exception
     */
    private boolean chooseUpdateStatusDTO(ProductCodeModelOfEntity entity) throws Exception {
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("packageStr", entity.getUpdateStatusDTOPackageStr());
        dataMap.put("dtoName", entity.getUpdateStatusDTOName());
        dataMap.put("value", createSerialVersionUID());
        dataMap.put("jsonUtilMethod", entity.getVoDtoJsonUtilMethod());

        dataMap.put("filedList", createFiled(entity, true));

        dataMap.put("methodList", createMethod(entity, true));

        dataMap.put("entity", entity);
        dataMap.put("dtoValue", "修改状态");


        return writeClassOfModel("dto.ftl", (entity.getDtoStr()), entity.getUpdateStatusDTOName(), entity, dataMap, "java");
    }

    /***
     * 生成 queryDTO
     * @param entity
     * @return
     * @throws Exception
     */
    private boolean chooseQueryDTO(ProductCodeModelOfEntity entity) throws Exception {
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("packageStr", entity.getUpdateDtoPackageStr());
        dataMap.put("value", createSerialVersionUID());

        dataMap.put("filedList", entity.getFiledModelOfEntities());
        dataMap.put("methodList", entity.getMethodModelOfEntities());
        dataMap.put("jsonUtilMethod", entity.getVoDtoJsonUtilMethod());
        dataMap.put("entity", entity);
        dataMap.put("dtoName", entity.getQueryDtoName());
        dataMap.put("dtoValue", "查询");

        return writeClassOfModel("querydto.ftl", (entity.getDtoStr()), entity.getQueryDtoName(), entity, dataMap, "java");
    }

    /***
     * 生成VO文件
     * @param entity
     * @return
     * @throws Exception
     */
    private boolean chooseVO(ProductCodeModelOfEntity entity) throws Exception {
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("packageStr", entity.getVoPackageStr());
        dataMap.put("voName", entity.getVoName());
        dataMap.put("value", createSerialVersionUID());

        dataMap.put("filedList", entity.getFiledModelOfEntities());
        dataMap.put("methodList", entity.getMethodModelOfEntities());
        dataMap.put("jsonUtilMethod", entity.getVoDtoJsonUtilMethod());
        dataMap.put("entity", entity);


        return writeClassOfModel("vo.ftl", (entity.getVoStr()), entity.getVoName(), entity, dataMap, "java");
    }


    /****
     * 组合entity对象
     * @param entity 实体
     * @param dataList 列集合
     * @param primaryKeyStr 主键
     * @return
     * @throws Exception
     */
    private boolean chooseEntityTemplate(ProductCodeModelOfEntity entity, List<Map<String, String>> dataList, String primaryKeyStr) throws Exception {

        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("tableName", entity.getTable());
        dataMap.put("entityName", entity.getEntityName());
        dataMap.put("filedList", entity.getFiledModelOfEntities());
        //  dataMap.put("methodList", entity.getMethodModelOfEntities());
        dataMap.put("localDateTime", entity.getLocalDateTime());
        dataMap.put("packageStr", entity.getEntityPackageStr());
        dataMap.put("dateFileds", entity.getDateFileds());
        dataMap.put("filedSize", entity.getFiledModelOfEntities().size());
        dataMap.put("dateUtils", entity.getDateUtils());
        dataMap.put("jsonUtilMethod", entity.getJsonUtilMethod());
        dataMap.put("entity", entity);
        dataMap.put("localDateTimeUtils", entity.getLocalDateTimeUtils());

        return writeClassOfModel("entity.ftl", entity.getEntityStr(), entity.getEntityName(), entity, dataMap, "java");
    }

    /***
     * 输出模板内容
     * @param templateName 模板 名称
     * @param pathStr 路径
     * @param fileName 文件名称
     * @param entity 实体 描述
     * @param dataMap 数据
     * @param fileEndChar 文件后缀
     * @return
     * @throws Exception
     */
    private boolean writeClassOfModel(String templateName, String pathStr, String fileName, ProductCodeModelOfEntity entity, Map<String, Object> dataMap, String fileEndChar) throws Exception {
        Writer out = null;
        OutputStreamWriter outputStreamWriter = null;
        FileOutputStream fileOutputStream = null;

        try {
            Template template = getDefinedTemplate(templateName, entity);
            String path = getPath(entity.getBasePath(), pathStr);
            File file = new File(path);
            if (!file.exists() || !file.isDirectory()) {
                file.mkdirs();
            }

            path = path + "/" + fileName + "." + fileEndChar;
            File outFile = new File(path);

            fileOutputStream = new FileOutputStream(outFile);
            outputStreamWriter = new OutputStreamWriter(fileOutputStream, "UTF-8");
            out = new BufferedWriter(outputStreamWriter, 1024);

            template.process(dataMap, out);

            fileOutputStream.flush();
            outputStreamWriter.flush();
            out.flush();

            System.out.println(path);
        } finally {
            IOUtils.closeQuietly(fileOutputStream);
            IOUtils.closeQuietly(outputStreamWriter);
            IOUtils.closeQuietly(out);
        }

        return Boolean.TRUE;
    }

    /****
     * 组合组合数据
     * @param entity 实体
     * @param dataList 列集合
     * @param primaryColumn 组件key
     * @return
     */
    private boolean combData(ProductCodeModelOfEntity entity, List<Map<String, String>> dataList, String primaryColumn) {
        Map<String, Object> data = new HashMap<>();
        data.put("packageStr", entity.getEntityPackageStr());
        data.put("tableName", entity.getTable());
        data.put("entityName", entity.getEntityName());

        List<FiledModelOfEntity> filedModelOfEntities = new ArrayList<>();
        List<MethodModelOfEntity> methodModelOfEntities = new ArrayList<>();
        List<String> dateFileds = new ArrayList<>();
        List<String> fileds = new LinkedList<String>();
        Map<String, String> columns = new HashMap<String, String>();
        Map<String, String> columnsType = new HashMap<String, String>();
        Map<String, String> columnsComment = new HashMap<String, String>();

        Map<String, String> getMethodNameMap = new HashMap<String, String>();
        Map<String, String> setMethodNameMap = new HashMap<String, String>();
        Map<String, Integer> filedLength = new HashMap<String, Integer>();
        Map<String, String> filedType = new HashMap<String, String>();
        Map<String, String> filedComment = new HashMap<String, String>();


        dataList.stream().forEach(dataMap -> {
            FiledModelOfEntity filedEntity = new FiledModelOfEntity();
            filedEntity.setComment(dataMap.get("COLUMN_COMMENT"));
            filedEntity.setColumn(dataMap.get("COLUMN_NAME"));
            filedEntity.setDbType(getDBType(dataMap.get("DATA_TYPE")));

            filedEntity.setJavaType(getJavaType(filedEntity.getDbType().toLowerCase(), entity));
            filedEntity.setName(getFiled(filedEntity.getColumn()));

            String numberFiled = isNum(filedEntity.getJavaType()) ? "1" : "0";
            Integer length = getLength(dataMap.get("CHARACTER_MAXIMUM_LENGTH"), dataMap.get("NUMERIC_PRECISION"), dataMap.get("numeric_scale"));

            filedEntity.setMaxLength(length);
            filedEntity.setNumberFiled(numberFiled);
            filedEntity.setDateFiled(isDateType(filedEntity.getDbType()) ? "1" : "0");

            if (Objects.equals(filedEntity.getColumn(), primaryColumn)) {
                entity.setIdFiled(filedEntity.getName());
                entity.setIdType(filedEntity.getJavaType());
                entity.setIdColumn(filedEntity.getColumn());
                entity.setIdDbType(filedEntity.getDbType());

                filedEntity.setIdFiled("1");
            }
            saveFiled(filedModelOfEntities, filedEntity, fileds, columns, columnsType, filedLength, length, columnsComment, filedComment, filedType);

            String formatName = formatName(filedEntity.getName());

            MethodModelOfEntity modelOfEntity = chooseMethod(formatName, getMethodNameMap, filedEntity, setMethodNameMap, methodModelOfEntities,null,null,1);

            if (isDate(filedEntity.getJavaType())) {
                dateFileds.add(filedEntity.getName());

                String startName = "start" + formatName;
                FiledModelOfEntity start = new FiledModelOfEntity();
                BeanUtils.copyProperties(filedEntity, start);
                start.setName(startName);
                start.setExist(2);

               String startFormName = formatName(startName);

                saveFiled(filedModelOfEntities, start, fileds, columns, columnsType, filedLength, length, columnsComment, filedComment, filedType);
                MethodModelOfEntity startMethodModel =  chooseMethod(startFormName, getMethodNameMap, filedEntity, setMethodNameMap, methodModelOfEntities,null,null,2);


                String endName = "end" + formatName;
                FiledModelOfEntity end = new FiledModelOfEntity();
                BeanUtils.copyProperties(filedEntity, end);
                end.setName(endName);
                end.setExist(2);
                end.setStartFiledName(startName);
                end.setGetFileName(modelOfEntity.getGetFileName());
                end.setFileName(modelOfEntity.getFiled());

                String endFormatName = formatName(endName);


                saveFiled(filedModelOfEntities, end, fileds, columns, columnsType, filedLength, length, columnsComment, filedComment, filedType);
                chooseMethod(endFormatName, getMethodNameMap, filedEntity, setMethodNameMap, methodModelOfEntities,startMethodModel,modelOfEntity,2);
            }
        });

        entity.setFiledModelOfEntities(filedModelOfEntities);
        entity.setFileds(fileds);
        entity.setColumns(columns);
        entity.setColumnsType(columnsType);
        entity.setColumnsComment(columnsComment);
        entity.setGetMethodNameMap(getMethodNameMap);
        entity.setSetMethodNameMap(setMethodNameMap);
        entity.setFiledLength(filedLength);
        entity.setFiledType(filedType);
        entity.setFiledComment(filedComment);
        entity.setMethodModelOfEntities(methodModelOfEntities);
        entity.setDateFileds(dateFileds);

        return Boolean.TRUE;
    }

    private static void saveFiled(List<FiledModelOfEntity> filedModelOfEntities, FiledModelOfEntity filedEntity, List<String> fileds, Map<String, String> columns, Map<String, String> columnsType, Map<String, Integer> filedLength, Integer length, Map<String, String> columnsComment, Map<String, String> filedComment, Map<String, String> filedType) {
        filedModelOfEntities.add(filedEntity);

        fileds.add(filedEntity.getName());
        columns.put(filedEntity.getName(), filedEntity.getName());
        columnsType.put(filedEntity.getColumn(), filedEntity.getDbType());
        filedLength.put(filedEntity.getName(), length);
        columnsComment.put(filedEntity.getColumn(), filedEntity.getComment());
        filedComment.put(filedEntity.getName(), filedEntity.getComment());
        filedType.put(filedEntity.getName(), filedEntity.getJavaType());
    }

    private static MethodModelOfEntity chooseMethod(String formatName, Map<String, String> getMethodNameMap, FiledModelOfEntity filedEntity, Map<String, String> setMethodNameMap,
                                                    List<MethodModelOfEntity> methodModelOfEntities, MethodModelOfEntity startMethodModel,MethodModelOfEntity modelOfEntity,Integer columnFlag) {
        String getMethodName = "get" + formatName;
        String setMethodName = "set" + formatName;
        getMethodNameMap.put(filedEntity.getName(), getMethodName);
        setMethodNameMap.put(filedEntity.getName(), setMethodName);

        MethodModelOfEntity methodEntity = new MethodModelOfEntity();
        methodEntity.setFiled(filedEntity.getName());
        methodEntity.setGetName(getMethodName);
        methodEntity.setSetName(setMethodName);
        methodEntity.setJavaType(filedEntity.getJavaType());
        methodEntity.setComment(filedEntity.getComment());
        methodEntity.setDataColumn(filedEntity.getColumn());
        methodEntity.setColumnFlag(columnFlag);
        if(Objects.nonNull(modelOfEntity)) {
            methodEntity.setGetFileName(modelOfEntity.getGetName());
        }

        if(Objects.nonNull(startMethodModel)) {
            methodEntity.setStartFiledName(startMethodModel.getGetName());
        }
        methodModelOfEntities.add(methodEntity);

        return methodEntity;
    }


    /***
     * 获取 数据库 中的最大值
     * @param val1
     * @param val2
     * @param val3
     * @return
     */
    private Integer getLength(String val1, String val2, String val3) {
        if (StringUtils.isNotEmpty(val1)) {
            BigDecimal bigDecimal = new BigDecimal(val1);
            return bigDecimal.longValue() > Integer.MAX_VALUE ? null : bigDecimal.intValue();
        }

        Integer val = 0;
        if (StringUtils.isNotEmpty(val2)) {
            val = val + Integer.valueOf(val2);
        }

        if (StringUtils.isNotEmpty(val3)) {
            val = val + Integer.valueOf(val3) + 1;
        }

        if (Objects.equals(val, 0)) {
            return null;
        }

        return val;
    }

    /***
     * 从数据库  类型 转换为java 类型
     * @param type
     * @return
     */
    private String getJavaType(String type, ProductCodeModelOfEntity entity) {
        if (contains(dateType, type)) {
            if (Objects.equals("1", entity.getLocalDateTime())) {
                return "java.time.LocalDateTime";
            }
            return "java.util.Date";
        } else if (contains(intType, type)) {
            return "java.lang.Integer";
        } else if (contains(booleanType, type)) {
            entity.setStatucFlag("1");
            return "java.lang.Boolean";
        } else if (contains(LongType, type)) {
            return "java.lang.Long";
        } else if (contains(bigdecType, type)) {
            return "java.math.BigDecimal";
        } else if (contains(LocalDateType, type)) {
            return "java.time.LocalDate";
        } else {
            return "java.lang.String";
        }
    }

    public String getDBType(String type) {
        if (Objects.equals(type.toLowerCase(), "int")) {
            return "INTEGER";
        } else if (Objects.equals(type.toLowerCase(), "text")) {
            return "VARCHAR";
        } else if (Objects.equals(type.toLowerCase(), "datetime")) {
            return "TIMESTAMP";
        }

        return type.toUpperCase();
    }

    /***
     * 数组 中是否包含数据
     * @param array
     * @param character
     * @return
     */
    private boolean contains(String[] array, String character) {
        if (ArrayUtils.isEmpty(array) || StringUtils.isEmpty(character)) {
            return Boolean.FALSE;
        }

        for (String str : array) {
            if (Objects.nonNull(str) && Objects.equals(character.toLowerCase(), str.toLowerCase())) {
                return Boolean.TRUE;
            }
        }
        return Boolean.FALSE;
    }

    /***
     * 根据 列名生成字段
     * @param column
     * @return
     */
    private String getFiled(String column) {
        String[] strs = column.split("_");
        StringBuilder build = new StringBuilder();

        for (int i = 0; i < strs.length; i++) {
            if (i == 0) {
                build.append(strs[i].substring(0, 1).toLowerCase());
            } else {
                build.append(strs[i].substring(0, 1).toUpperCase());
            }

            if (strs[i].length() > 1) {
                build.append(StringUtils.substring(strs[i], 1).toLowerCase());
            }
        }
        return build.toString();
    }

    /****
     * 初始化bean
     * @param entity
     */
    private ProductCodeModelOfEntity initEntity(ProductCodeModelOfEntity entity) {
        String className = format(entity.getTable(), entity.getReplateStr(), entity.getStartCharacter());
        String dto = entity.getDtoStr();
        if (entity.isChanageDTOPackStr()) {
            dto = entity.getDtoStr() + "." + org.apache.commons.lang3.StringUtils.substring(className, 0, 1).toLowerCase() + org.apache.commons.lang3.StringUtils.substring(className, 1);
            entity.setDtoStr(dto.toLowerCase());
        }
        entity.setQueryDtoName(className + "QueryDTO");
        entity.setQueryDtoPackageStr(getPackageStr(dto).toLowerCase());
        entity.setQueryDtoPath(entity.getQueryDtoPackageStr() + "." + entity.getQueryDtoName());

        entity.setAddDtoName(className + "AddDTO");
        entity.setAddDtoPackageStr(getPackageStr(dto).toLowerCase());
        entity.setAddDtoPath(entity.getAddDtoPackageStr() + "." + entity.getAddDtoName());

        entity.setUpdateDtoName(className + "UpdateDTO");
        entity.setUpdateDtoPackageStr(getPackageStr(dto).toLowerCase());
        entity.setUpdateDtoPath(entity.getUpdateDtoPackageStr() + "." + entity.getUpdateDtoName());

        entity.setUpdateStatusDTOName(className + "UpdateStatusDTO");
        entity.setUpdateStatusDTOPackageStr(getPackageStr(dto).toLowerCase());
        entity.setUpdateStatusDTOPath(entity.getUpdateStatusDTOPackageStr() + "." + entity.getUpdateStatusDTOName());

        entity.setVoName(className + "VO");
        entity.setVoPackageStr(getPackageStr(entity.getVoStr()).toLowerCase());
        entity.setVoPath(entity.getVoPackageStr() + "." + entity.getVoName());

        entity.setEntityName(className);
        entity.setEntityPackageStr(getPackageStr(entity.getEntityStr()));
        entity.setEntityPath(entity.getEntityPackageStr() + "." + entity.getEntityName());

        entity.setMapperXMLName(className + "Mapper");

        entity.setMapperName(className + "Mapper");
        entity.setRepostioryName(formatResourceName(entity.getMapperName()));
        entity.setMapperPackageStr(getPackageStr(entity.getMapperStr()));
        entity.setMapperPath(entity.getMapperPackageStr() + "." + entity.getMapperName());

        entity.setServiceImplName(className + "ServiceImpl");
        entity.setServiceImplPackageStr(getPackageStr(entity.getServiceImplStr()));
        entity.setServicePath(entity.getServiceImplPackageStr() + "." + entity.getServiceImplName());

        entity.setServiceName(className + "Service");
        entity.setServicePackageStr(getPackageStr(entity.getServiceStr()));
        entity.setServicePath(entity.getServicePackageStr() + "." + entity.getServiceName());
        entity.setServiceNm(formatResourceName(entity.getServiceName()));

        entity.setControllerName(className + "Controller");
        entity.setControllerPackageStr(getPackageStr(entity.getControllerStr()));
        entity.setMapperPath(entity.getMapperPackageStr() + "." + entity.getMapperName());
        entity.setUrl(formatURL(entity));
        entity.setFunctionName(formatFunctionName(className));
        entity.setResourceName(formatResourceName(className));

        if (Objects.equals(entity.getIsAuthorityURL(), "1")) {
            entity.setAuthorityURL(formatAuthorityURL(entity));
        }

        if (StringUtils.isEmpty(entity.getBasePath())) {
            entity.setBasePath(entity.getDefaultBasePath() + "/" + UUID.randomUUID());
        }

        return entity;
    }

    /***
     * 格式包名称
     * */
    private String getPackageStr(String str) {
        if (StringUtils.isEmpty(str)) {
            return null;
        }

        if (StringUtils.indexOf(str, ";") > 0) {
            return StringUtils.substringAfter(str, ";");
        }

        return null;
    }

    /***
     * 组合类名
     * @param character 需要处理的字符串
     * @param replateCharacter 需要替换的名称
     * @param startCharacter 开头字符串
     * @return
     */
    private String format(String character, String replateCharacter, String startCharacter) {
        if (StringUtils.isNotEmpty(replateCharacter)) {
            character = character.replace(replateCharacter, "");
        }

        if (StringUtils.isNotEmpty(startCharacter)) {
            character = startCharacter + "_" + character;
        }

        String[] strs = character.split("_");
        StringBuilder build = new StringBuilder();

        for (String str : strs) {
            build.append(StringUtils.substring(str, 0, 1).toUpperCase());

            if (StringUtils.length(str) > 1) {
                build.append(StringUtils.substring(str, 1).toLowerCase());
            }
        }
        return build.toString();
    }

    /***
     * 根据模板名称获取模板数据
     * @param templateName 模板名称
     * @return
     * @throws Exception
     */
    private Template getDefinedTemplate(String templateName, ProductCodeModelOfEntity entity) throws Exception {
        //配置类
        Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);

        cfg.setDirectoryForTemplateLoading(new File(getModelPath(entity)));
        cfg.setDefaultEncoding("UTF-8");
        cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
        return cfg.getTemplate(templateName);
    }

    private String getTableComment(ProductCodeModelOfEntity entity) {
        String sql = "SELECT table_name,table_comment   FROM information_schema.TABLES   WHERE table_schema='" + entity.getDbName() + "' and TABLE_NAME ='" + entity.getTable() + "' ORDER BY table_name";
        List<Map<String, String>> lists = ConnectionUtil.select(sql, entity.getIp(), entity.getUser(), entity.getPwd());
        return ((null == lists || lists.size() == 0)) ? "" : lists.get(0).get("TABLE_COMMENT");
    }

    /***
     * 根据 表 名称查询列名 集合
     * @param entity
     * @return
     */
    private List<Map<String, String>> getColumnsData(ProductCodeModelOfEntity entity) {
        String sql = "select column_name,data_type,Character_maximum_length,numeric_precision,column_comment,numeric_scale from information_schema.columns where table_schema = '"
                + entity.getDbName() + "'  and table_name = '" + entity.getTable() + "'  ORDER BY ordinal_position";
        return ConnectionUtil.select(sql, entity.getIp(), entity.getUser(), entity.getPwd());
    }

    /***
     * 查询主键信息
     * @return
     */
    private String getPrimaryKeyColumns(ProductCodeModelOfEntity entity) {
        String sql = "SELECT c.COLUMN_NAME FROM  INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS t, information_schema.TABLES AS ts, information_schema.KEY_COLUMN_USAGE AS c where  t.TABLE_NAME = ts.TABLE_NAME  AND ts.TABLE_NAME  = c.TABLE_NAME AND t.TABLE_SCHEMA = '"
                + entity.getDbName() + "'  AND t.CONSTRAINT_TYPE = 'PRIMARY KEY'  and t.TABLE_NAME= '" + entity.getTable() + "'";
        List<Map<String, String>> lists = ConnectionUtil.select(sql, entity.getIp(), entity.getUser(), entity.getPwd());

        return ((null == lists || lists.size() == 0)) ? "id" : lists.get(0).get("COLUMN_NAME");

    }

    /***
     * 根据数据库查询所有的表名称
     * @return
     */
    public List<Map<String, String>> getTables(ProductCodeModelOfEntity entity) {
        String sql = "select table_name from information_schema.tables where table_schema='" + entity.getDbName() + "'";
        List<Map<String, String>> lists = ConnectionUtil.select(sql, entity.getIp(), entity.getUser(), entity.getPwd());

        return ConnectionUtil.select(sql, entity.getIp(), entity.getUser(), entity.getPwd());
    }

    /***
     * 计算路径
     * @param batchPath
     * @param str
     * @return
     */
    private String getPath(String batchPath, String str) {
        StringBuilder builder = new StringBuilder();
        builder.append(batchPath);

        if (StringUtils.isNotEmpty(str)) {
            builder.append("/");
            str = StringUtils.replace(str, ".", "/");
            str = StringUtils.replace(str, ";", "/");
            builder.append(str);
        }
        return builder.toString();
    }


    private String getModelPath(ProductCodeModelOfEntity entity) {
        String path = System.getProperty("user.dir");
        String modelPath = "/models";
        if (StringUtils.isNotEmpty(entity.getModelDictionName())) {
            modelPath = "/" + entity.getModelDictionName();
        }
        File file = new File(path + modelPath);
        return file.exists() ? file.getAbsolutePath() + "/" : path + "/src/main/resources" + modelPath + "/";
    }

    /***
     * 判断是否是日期 格式
     * @return
     */
    private boolean isDate(String javaType) {
        return Optional.ofNullable(javaType).map(type -> {
            return Objects.equals("java.util.Date", type.trim()) || Objects.equals("java.time.LocalDateTime", type);
        }).orElse(Boolean.FALSE);
    }

    /***
     * 格式化名称（Java名称）
     * @param val
     * @return
     */
    private String formatName(String val) {
        String formatName = StringUtils.substring(val, 0, 1).toUpperCase();
        if (StringUtils.length(val) > 1) {
            formatName = formatName + StringUtils.substring(val, 1);
        }
        return formatName;
    }

    /***
     * 格式化并生成URL
     * @param entity
     * @return
     */
    private String formatURL(ProductCodeModelOfEntity entity) {
        String url = StringUtils.replace(StringUtils.replace(entity.getTable(), "_", "/"), "-", "/").toLowerCase();
        if (StringUtils.isNotEmpty(entity.getStartCharacter())) {
            url = entity.getStartCharacter() + "/" + url;
        }

        return url;
    }

    /***
     *格式化函数名称
     *
     * @author liujun
     * @date 2024/6/19 10:26
     * @param str
     * @return java.lang.String
     */
    private String formatFunctionName(String str) {
        int length = org.apache.commons.lang3.StringUtils.length(str);
        if (length == 0) {
            return "";
        }

        if (length == 1) {
            return org.apache.commons.lang3.StringUtils.substring(str, 0, 1).toUpperCase();
        }
        return org.apache.commons.lang3.StringUtils.substring(str, 0, 1).toUpperCase() + org.apache.commons.lang3.StringUtils.substring(str, 1);
    }

    /***
     *
     *格式化权限URL
     * @author liujun
     * @date 2024/6/19 9:44
     * @param entity
     * @return java.lang.String
     */
    private String formatAuthorityURL(ProductCodeModelOfEntity entity) {
        String str = StringUtils.replace(StringUtils.replace(entity.getTable(), "_", ":"), "-", ":").toLowerCase();
        if (StringUtils.isNotEmpty(entity.getStartCharacter())) {
            str = entity.getStartCharacter() + ":" + str;
        }
        return str;
    }

    private String formatResourceName(String str) {
        int length = org.apache.commons.lang3.StringUtils.length(str);
        if (length == 0) {
            return "";
        }

        if (length == 1) {
            return org.apache.commons.lang3.StringUtils.substring(str, 0, 1).toLowerCase();
        }
        return org.apache.commons.lang3.StringUtils.substring(str, 0, 1).toLowerCase() + org.apache.commons.lang3.StringUtils.substring(str, 1);
    }

    /***
     * 添加操作人员字段
     * @return
     */
    private FiledModelOfEntity createOperatorCharOfFiled() {
        FiledModelOfEntity filedModelOfEntity = new FiledModelOfEntity();
        filedModelOfEntity.setName("operator");
        filedModelOfEntity.setComment("操作人员");
        filedModelOfEntity.setJavaType("java.lang.String");

        return filedModelOfEntity;
    }

    /***
     * 添加操作人员方法字段
     * @return
     */
    private MethodModelOfEntity createOperatorOfMethod() {
        MethodModelOfEntity methodModelOfEntity = new MethodModelOfEntity();
        methodModelOfEntity.setComment("操作人员");
        methodModelOfEntity.setJavaType("java.lang.String");
        methodModelOfEntity.setSetName("setOperator");
        methodModelOfEntity.setFiled("operator");
        methodModelOfEntity.setGetName("getOperator");
        return methodModelOfEntity;
    }

    /***
     * 判断是否 是数字
     * @param javaType
     * @return
     */
    private boolean isNum(String javaType) {
        return ArrayUtils.contains(nums, javaType);
    }

    private boolean isDateType(String javaType) {
        return ArrayUtils.contains(dateType, javaType);
    }

    /***
     * 创建列信息
     *
     * @author liujun
     * @date 2024/6/19 13:21
     * @param entity
     * @param isAddCreateOperator 是否添加操作人员
     * @return java.util.List<com.entity.FiledModelOfEntity>
     */
    private List<FiledModelOfEntity> createFiled(ProductCodeModelOfEntity entity, boolean isAddCreateOperator) {
        List<FiledModelOfEntity> fileds = new ArrayList<>();
        if (Objects.nonNull(entity.getFiledModelOfEntities())) {
            fileds.addAll(entity.getFiledModelOfEntities());
        }
        if (isAddCreateOperator) {
            fileds.add(createOperatorCharOfFiled());
        }
        return fileds;
    }

    /***
     *
     *
     * @author liujun
     * @date 2024/6/19 13:23
     * @param entity
     * @param isAddCreateOperator  是否添加操作人员
     * @return java.util.List<com.entity.MethodModelOfEntity>
     */
    private List<MethodModelOfEntity> createMethod(ProductCodeModelOfEntity entity, boolean isAddCreateOperator) {
        List<MethodModelOfEntity> methods = new ArrayList<>();
        if (Objects.nonNull(entity.getMethodModelOfEntities())) {
            List<MethodModelOfEntity> methos = entity.getMethodModelOfEntities().stream().filter(method -> Objects.equals("java.lang.Boolean", method.getJavaType())).collect(Collectors.toList());
            if (Objects.nonNull(methos) && methos.size() > 0) {
                methods.addAll(methos);
            }
        }

        methods.add(createOperatorOfMethod());
        return methods;
    }

    /***
     * 生产SerialVersionUID
     * @return
     */
    private String createSerialVersionUID() {
        return RandomUtils.nextLong(9999, 999999999) + "";
    }
}
